﻿using iTool.ClusterComponent.Model;
using iTool.ClusterComponent.Model.History;
using Orleans.Concurrency;
using Orleans.Runtime;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace iTool.ClusterComponent
{
    public class DashboardClient : IDashboardClient
    {
        private readonly IDashboardService dashboardGrain;
        private readonly IDashboardRemindersService remindersGrain;
        private readonly IClusterService clusterService;

        public DashboardClient(IClusterService clusterService)
        {
            this.clusterService = clusterService;
            dashboardGrain = clusterService.GetService<IDashboardService>();
            remindersGrain = clusterService.GetService<IDashboardRemindersService>();
        }

        public async Task<Immutable<DashboardCounters>> DashboardCounters()
        {
            return await dashboardGrain.GetCounters().ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, GrainTraceEntry>>> ClusterStats()
        {
            return await dashboardGrain.GetClusterTracing().ConfigureAwait(false);
        }

        public async Task<Immutable<ReminderResponse>> GetReminders(int pageNumber, int pageSize)
        {
            return await remindersGrain.GetReminders(pageNumber, pageSize).ConfigureAwait(false);
        }

        public async Task<Immutable<SiloRuntimeStatistics[]>> HistoricalStats(string siloGrain)
        {
            var grain = clusterService.GetService<INoderService>(siloGrain);
            return await grain.GetRuntimeStatistics().ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, string>>> SiloProperties(string siloGrain)
        {
            var grain = clusterService.GetService<INoderService>(siloGrain);
            return await grain.GetExtendedProperties().ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, GrainTraceEntry>>> SiloStats(string siloAddress)
        {
            return await dashboardGrain.GetSiloTracing(siloAddress).ConfigureAwait(false);
        }

        public async Task<Immutable<StatCounter[]>> GetCounters(string siloAddress)
        {
            var grain = clusterService.GetService<INoderService>(siloAddress);
            return await grain.GetCounters().ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, Dictionary<string, GrainTraceEntry>>>> GrainStats(string grainName)
        {
            return await dashboardGrain.GetGrainTracing(grainName).ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, GrainMethodAggregate[]>>> TopGrainMethods()
        {
            return await dashboardGrain.TopGrainMethods().ConfigureAwait(false);
        }


        public async Task<Immutable<Dictionary<string, long>>> GetCloudFunctionTracing()
        { 
            return await dashboardGrain.GetCloudFunctionTracing().ConfigureAwait(false);
        }

        public async Task<Immutable<Dictionary<string, long>>> GetHttpRequestStatistics()
        {
            return await dashboardGrain.GetHttpRequestStatistics().ConfigureAwait(false);
        }

        public async Task<StatisticsResult> GetConnectionStatistics()
        {
            return await dashboardGrain.GetConnectionStatistics().ConfigureAwait(false);
        }


        public async Task<GatewayStatisticOptions> GetGatewayStatisticOptions() 
        {
            var result = new GatewayStatisticOptions();
            var httprequest = this.GetHttpRequestStatistics();
            var fn = this.GetCloudFunctionTracing();
            var connect = this.GetConnectionStatistics();

            await Task.WhenAll(httprequest, fn, connect);
            result.HttpRequest = httprequest.Result.Value.OrderBy(item => item.Key).ToList();
            result.CloudFunction = fn.Result.Value.OrderBy(item => item.Key).ToList();
            result.OnlineCount = connect.Result.OnlineCount;
            result.DayOnlineCount = connect.Result.DayOnlineCount;
            result.ClientTypes = connect.Result.ClientTypes;
            result.PlatformTypes = connect.Result.PlatformTypes;
            result.ProvinceTypes = connect.Result.ProvinceTypes;

            return result;
        }
    }
}
